<!--
 * @Description: 轮播通知
 * @Version: 0.0.1
 * @Autor: zhj1214
 * @Date: 2024-05-06 16:59:39
 * @LastEditors: zhj1214
 * @LastEditTime: 2024-10-16 17:42:13
-->
<template>
  <div v-show="props.list.length > 0" class="broadcast items-center">
    <!-- 第一段 -->
    <div
      v-if="broadcast.startList.length > 0"
      class="items-center broadcast-first"
      :class="{
        'broadcast-firstStart1': el01EndPx != '0px' && firstRef,
      }"
      style="position: absolute; will-change: transform"
      ref="firstRef"
      @animationiteration="broadcastEnd(1)"
      @animationiteration="broadcastEnd"
    >
      <template v-for="(item, index) in broadcast.startList">
        <div
          v-if="!`${item.id}`.includes('null')"
          :key="item.id"
          class="broadcast-item items-center"
        >
          <ImgNuxt
            class="broadcast-item-img"
            :src="item.avatar || imgUrl.avatarDefault"
            :placeholder="imgUrl.avatarDefault"
            isHttp
          ></ImgNuxt>

          <div class="broadcast-item-info items-center">
            <div
              class="broadcast-item-nick"
              style="min-width: 28px; text-align: center"
            >
              {{ item.nickname ? item.nickname.substring(0, 11) : "--" }}
              <span style="margin-left: -4px">
                {{ item.nickname && item.nickname.length > 11 ? "..." : "" }}
              </span>
            </div>
            <div
              class="broadcast-item-nick"
              style="min-width: 55px; text-align: center"
            >
              {{ $t("mvp.mining.text13") }}
            </div>
            <div class="broadcast-item-bdc">{{ item.acquireAmount }}</div>
            <div class="broadcast-item-nick">BDC</div>
            <div class="items-center" style="min-width: 39px">
              {{ item.miningtext }}
            </div>
          </div>
        </div>
      </template>
    </div>
    <!-- 第二段 -->
    <div
      v-if="broadcast.endList.length > 0"
      class="items-center broadcast-second"
      :class="{
        'broadcast-secondStart': isCanLoadSecond && el1EndPx != '0px',
      }"
      style="position: absolute; will-change: transform"
      ref="secondRef"
      @animationiteration="broadcastEnd"
    >
      <template v-for="(item, index) in broadcast.endList">
        <div
          :key="item.id"
          class="broadcast-item items-center"
          :style="{ 'margin-right': `${broadcast.itemSpace}px` }"
        >
          <ImgNuxt
            class="broadcast-item-img"
            :src="item.avatar || imgUrl.avatarDefault"
            :placeholder="imgUrl.avatarDefault"
            isHttp
          ></ImgNuxt>
          <div class="broadcast-item-info items-center">
            <div
              class="broadcast-item-nick"
              style="min-width: 28px; text-align: center"
            >
              {{ item.nickname ? item.nickname.substring(0, 11) : "--" }}
              <span style="margin-left: -4px">
                {{ item.nickname && item.nickname.length > 11 ? "..." : "" }}
              </span>
            </div>
            <div
              class="broadcast-item-nick"
              style="min-width: 55px; text-align: center"
            >
              {{ $t("mvp.mining.text13") }}
            </div>
            <div class="broadcast-item-bdc">{{ item.acquireAmount }}</div>
            <div class="broadcast-item-nick">BDC</div>
            <div class="items-center" style="min-width: 39px">
              {{ item.miningtext }}
            </div>
          </div>
        </div>
      </template>
    </div>
  </div>
</template>
<script setup lang="ts" name="broadcast">
import { ref, reactive, onMounted, computed, nextTick } from "vue";
import { getOssFileUrl } from "@/utils";
import { useWindowSize } from "@vant/use";

const props = withDefaults(
  defineProps<{
    list: any;
    loop?: boolean;
  }>(),
  {
    list: [],
    loop: false,
  }
);
const emit = defineEmits(["end"]);

const imgUrl = getOssFileUrl({
  avatarDefault: "/image/avatar-default.png",
});

const broadcast = reactive({
  endIdx: 0, // 3 也是组件最小长度
  list: [],
  startList: [],
  endList: [],
  pace: 3, // 目前不能改,因为动画时间是固定的
  animationIdx: 0, // 当前动画的索引
});

// 动画开始
const isCanLoadSecond = ref(false);
const animationstart = (val: number) => {
  // console.log("第", val, "段动画------开始");
  if (!isCanLoadSecond.value) {
    setTimeout(() => {
      isCanLoadSecond.value = true;
    }, 8000);
  }
};

// const isCanLoadFirst1 = ref(false); // 第一段,第二组动画开始
// const isCanLoadSecond = ref(false); // 第二段,动画开始
// 一次动画结束:展示了两段数据
const broadcastEnd = (val: any) => {
  let type = -1;
  if (val.animationName.includes("leftgroup0")) {
    type = 0;
    // nextTick(() => {
    //   // if (!isCanLoadSecond.value) isCanLoadSecond.value = true;
    //   if (!isCanLoadFirst1.value) isCanLoadFirst1.value = true;
    // });
  } else if (val.animationName.includes("leftgroup1")) {
    type = 1;
    // nextTick(() => {
    //   if (isCanLoadFirst1.value) isCanLoadFirst1.value = false;
    // });
  } else if (val.animationName.includes("leftgroup2")) {
    type = 2;
  }
  // console.log("第", val.animationName, "动画结束了", type);
  if (type <= 0) return;

  // broadcast.animationIdx = type;
  // 1. 赋值新数据
  if (type == 1) {
    broadcast.startList = broadcast.list.slice(
      broadcast.endIdx,
      broadcast.endIdx + broadcast.pace
    );

    // 无循环
    if (!props.loop && broadcast.startList.length > 0) {
      while (broadcast.startList.length < 3) {
        (broadcast.startList as any).push({
          id: `null${broadcast.startList.length}`,
          avatar: "",
          acquireAmount: "",
          nickname: "",
        });
      }
    }
  }
  if (type == 2) {
    broadcast.endList = broadcast.list.slice(
      broadcast.endIdx,
      broadcast.endIdx + broadcast.pace
    );

    // 无循环
    if (!props.loop) {
      if (broadcast.endList.length > 0) {
        while (broadcast.endList.length < 3) {
          (broadcast.endList as any).push({
            id: `null${broadcast.endList.length}`,
            avatar: "",
            acquireAmount: "",
            nickname: "",
          });
        }
      }
    }
  }
  // 2. 重新计算 endIdx
  broadcast.endIdx = broadcast.endIdx + broadcast.pace;
  // console.log(type, "--type--", broadcast.endIdx, "--", broadcast.list.length);

  // 4. 如果设置了循环,则重置要截取的索引值
  if (broadcast.endIdx >= broadcast.list.length && props.loop) {
    broadcast.endIdx = 0;
  } else {
    emit("end");
  }
};
const { width } = process.client ? useWindowSize() : { width: ref(320) };
const firstRef = ref(null);
const secondRef = ref(null);
const firstWidth = ref(0); // 第一段: 宽度
const secondWidth = ref(0); // 第二段: 宽度

// 重新获取每个元素的宽度
const getElWidth = (val: number) => {
  if (val == 1 && firstRef.value) {
    const rect = firstRef.value.getBoundingClientRect();
    // console.log(firstRef.value.offsetWidth, "第一段 的宽度", rect.width);
    if (firstWidth.value != rect.width) firstWidth.value = rect.width;
  }
  if (val == 2 && secondRef.value) {
    const rect = secondRef.value.getBoundingClientRect();
    // console.log("第二段 的宽度", rect.width);
    if (secondWidth.value != rect.width) secondWidth.value = rect.width;
  }
};

// 第一段: 开始位置
const el0StartPx = computed(() => {
  return `${width.value}px`;
});
// 第一段: 第一个动画的,结束位置
const el0EndPx = computed(() => {
  if (firstWidth.value) {
    if (firstWidth.value > width.value) {
      return `-${firstWidth.value - width.value}px`;
    } else {
      return `${width.value - firstWidth.value}px`;
    }
  }
  return `0px`;
});
// 第一段: 第二个动画的,结束位置
const el01EndPx = computed(() => {
  if (firstWidth.value) {
    if (firstWidth.value * 2 > width.value) {
      return `-${firstWidth.value * 2 - width.value}px`;
    } else {
      return `${width.value - firstWidth.value * 2}px`;
    }
  }
  return `0px`;
});
// 第二段: 开始位置
const el1StartPx = computed(() => {
  return `${width.value}px`;
});
// 第二段:结束位置
const el1EndPx = computed(() => {
  if (secondWidth.value) {
    return `-${secondWidth.value * 2 - width.value}px`;
  }
  return `0px`;
});

const startListWatch = watch(
  () => broadcast.startList,
  (newVal) => {
    if (newVal && newVal.length > 0) {
      // nextTick 不行,无法获取到真实的宽度
      setTimeout(() => {
        getElWidth(1);
      }, 1);
    }
  },
  {
    immediate: true,
    deep: true,
  }
);

const endListWatch = watch(
  () => broadcast.endList,
  (newVal) => {
    if (newVal && newVal.length > 0) {
      // nextTick 不行,无法获取到真实的宽度
      setTimeout(() => {
        getElWidth(2);
      }, 1);
    }
  },
  {
    immediate: true,
    deep: true,
  }
);

/**
 * @description: 初始化
 * 1. 整理数据
 * 2. 分割数据源
 */
const init = () => {
  if (!props.list) return;
  if (props.loop) {
    if (props.list.length <= 1) return;
    // 1. 数据整理: 使用得数据达到 broadcast.pace 的倍数, 并且数组的长度大于等于 6
    if (props.list.length % broadcast.pace !== 0 || props.list.length <= 6) {
      if (props.list.length < 6) {
        broadcast.list = props.list.concat(props.list).concat(props.list);
      } else {
        broadcast.list = props.list.concat(props.list);
      }
    } else {
      broadcast.list = props.list;
    }

    // 2. 初始值,默认broadcast.pace 个数一段,可以自定义,当前是 3 个一段
    broadcast.endIdx = broadcast.pace;
    // 3.1 截取第一段
    broadcast.startList = broadcast.list.slice(0, broadcast.endIdx);
    // 3.2 截取第二段
    broadcast.endList = broadcast.list.slice(
      broadcast.endIdx,
      broadcast.endIdx + broadcast.pace
    );
    broadcast.endIdx += broadcast.pace; // 注意:数组长度至少大于 6
  } else {
    if (props.list.length <= 3) {
      broadcast.startList = props.list;
      while (broadcast.startList.length < 3) {
        (broadcast.startList as any).push({
          id: `null${broadcast.startList.length}`,
          avatar: "",
          acquireAmount: "",
          nickname: "",
        });
      }
      broadcast.endIdx = broadcast.pace;
    } else if (props.list.length >= 6) {
      broadcast.list = props.list;
      // 1. 初始值,默认broadcast.pace 个数一段,可以自定义,当前是 3 个一段
      broadcast.endIdx = broadcast.pace;
      // 1.1 截取第一段
      broadcast.startList = broadcast.list.slice(0, broadcast.endIdx);
      // 1.2 截取第二段
      broadcast.endList = broadcast.list.slice(
        broadcast.endIdx,
        broadcast.endIdx + broadcast.pace
      );
      broadcast.endIdx += broadcast.pace; // 注意:数组长度至少大于 6
    } else {
      broadcast.list = props.list;
      // 1. 初始值,默认broadcast.pace 个数一段,可以自定义,当前是 3 个一段
      broadcast.endIdx = broadcast.pace;
      // 1.1 截取第一段
      broadcast.startList = broadcast.list.slice(0, broadcast.endIdx);
      // 1.2 截取第二段
      broadcast.endList = broadcast.list.slice(
        broadcast.endIdx,
        broadcast.endIdx + broadcast.pace
      );
      broadcast.endIdx += broadcast.pace;
      while (broadcast.endList.length < 3) {
        (broadcast.endList as any).push({
          id: `null${broadcast.endList.length}`,
          avatar: "",
          acquireAmount: "",
          nickname: "",
        });
      }
      // console.log("broadcast--", broadcast);
    }
  }
};

// 监听数据变化
const listWatch = watch(
  () => props.list,
  (newVal) => {
    if (newVal && newVal.length > 0) {
      init();
    }
  }
);

onMounted(() => {
  init();
});

onBeforeUnmount(() => {
  listWatch && listWatch();
  endListWatch && endListWatch();
  startListWatch && startListWatch();
});
</script>
<style scoped lang="scss">
.popover {
  &-text {
    padding: 6 * 2px 12 * 2px;
    color: #fff;
    font-size: 11 * 2px;
  }
}

.broadcast {
  transform: translate3d(0, 0, 0); // 启用硬件加速
  @keyframes leftgroup1 {
    from {
      transform: translateX(v-bind("firstStartPosition"));
    }
    to {
      transform: translateX(v-bind("firstEndPosition"));
    }
  }
  @keyframes leftgroup2 {
    from {
      transform: translateX(v-bind("secondStartPosition"));
    }
    to {
      transform: translateX(v-bind("secondEndPosition"));
    }
  }

  position: relative;
  width: 100vw;
  height: 30 * 2px;
  overflow: hidden;

  &-firstStart {
    transform: translate3d(0, 0, 0); // 启用硬件加速
    position: absolute;
    animation: leftgroup1 8s linear infinite !important;
  }
  &-secondStart {
    transform: translate3d(0, 0, 0); // 启用硬件加速
    position: absolute;
    animation: leftgroup2 13.31s linear infinite;
  }
  &-pause {
    animation-play-state: paused !important;
  }
  &-item {
    border-radius: 100px;
    background: rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(12px);
    padding: 2 * 2px 0;

    &-img {
      overflow: hidden;
      min-width: 14 * 2px !important;
      max-width: 14 * 2px !important;
      height: 14 * 2px;
      border-radius: 100px;
      border: 1px solid #4aa1ff;
      margin: 0 9 * 2px;
    }
    &-info {
      height: 18 * 2px;
      margin-right: 6 * 2px;
    }
    &-nick {
      color: #fff;
      font-size: 11 * 2px;
      text-wrap: nowrap;
      white-space: nowrap;
      margin-right: 9 * 2px;
    }
    &-bdc {
      margin-right: 9 * 2px;
      color: #007bff;
      font-size: 11 * 2px;
      font-weight: 590;
    }
  }
}
</style>
<style lang="scss">
.popover-bg {
  .van-popover__content {
    background: transparent !important;
  }
  .van-popover__arrow {
    color: rgba(0, 0, 0, 0.3);
  }
  .van-popover__content {
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(6px);
  }
}
</style>
